package org.dailydev.mojo.birt;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.apache.maven.model.FileSet;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.FileUtils;
import org.dailydev.mojo.birt.runner.commandline.HTMLRenderConfig;
import org.dailydev.mojo.birt.runner.commandline.ReportRunner;

/**
 */
public abstract class AbstractBirtMojo extends AbstractMojo {

	/**
	 * BIRT Runtime home
	 * 
	 * @parameter expression="${birt.home}" default-value="env.BIRT_HOME"
	 * @since 1.0
	 */
	private String birtHome;

	/**
	 * Output folder
	 * 
	 * @parameter expression="${birt.output}" default-value="target/report"
	 * @since 1.0
	 */
	private File output;

	/**
	 * {@link org.apache.maven.model.FileSet}
	 * 
	 * @parameter expression="${birt.reports}"
	 * @required
	 * @since 1.0
	 */
	private FileSet reports;

	/**
	 * {@link ParameterSet}
	 * 
	 * @parameter expression="${birt.parameters}"
	 * @since 1.0
	 */
	private Parameter[] parameters;

	/**
	 * @parameter expression="${birt.locale}" default-value="en"
	 * @since 1.0
	 */
	private String locale;

	/**
	 * @parameter expression="${birt.parametersFile}"
	 * @since 1.0
	 */
	private File parametersFile;

	/**
	 * @parameter expression="${birt.page}"
	 * @since 1.0
	 */
	private Integer page;

	/**
	 * Report format
	 * 
	 * @parameter expression="${birt.format}" default-value="HTML"
	 * @since 1.0
	 */
	private String format = ReportRunner.FORMAT_HTML;

	/**
	 * Configuration for HTML rendering
	 * 
	 * @parameter expression="${birt.htmlConfig}"
	 * @since 1.0
	 */
	private HTMLRenderConfig htmlConfig = new HTMLRenderConfig();

	/**
	 * @parameter expression="${project}"
	 * @readonly
	 */
	protected MavenProject mavenProject;

	/**
	 * 
	 */
	public AbstractBirtMojo() {
		super();
	}

	/**
	 * @param reportRunner
	 * @throws MojoExecutionException
	 */
	protected void configureReportRunner(ReportRunner reportRunner) throws MojoExecutionException {
		reportRunner.setBirtHome(this.getBirtHome());
		reportRunner.setFormat(this.getFormat());
		reportRunner.setHtmlConfig(this.getHtmlConfig());
		reportRunner.setOutput(this.getOutput());
		reportRunner.setReports(this.getReports());
		reportRunner.setParameters(this.getParameters());
		reportRunner.setParametersFile(this.getParametersFile());
		reportRunner.setLocale(this.getLocale());
		reportRunner.setPage(this.getPage());
	}

	/** {@inheritDoc} */
	public void execute() throws MojoExecutionException {
		ReportRunner reportRunner = instantiateReportRunner();
		configureReportRunner(reportRunner);
		reportRunner.execute();
	}

	/**
	 * @return
	 */
	public String getBirtHome() {
		return this.birtHome;
	}

	/**
	 * @param list
	 * @return
	 */
	protected String getCommaSeparatedList(List list) {
		StringBuffer buffer = new StringBuffer();
		for (Iterator iterator = list.iterator(); iterator.hasNext();) {
			Object element = iterator.next();
			buffer.append(element.toString());
			if (iterator.hasNext()) {
				buffer.append(",");
			}
		}
		return buffer.toString();
	}

	/**
	 * @return
	 */
	protected String getFormat() {
		return this.format;
	}

	/**
	 * @return
	 */
	protected HTMLRenderConfig getHtmlConfig() {
		return this.htmlConfig;
	}

	/**
	 * @return
	 */
	protected String getLocale() {
		return this.locale;
	}

	/**
	 * @return
	 */
	protected File getOutput() {
		String targetDirectory = this.mavenProject.getBuild().getDirectory();
		if (this.output == null) {
			this.output = new File(targetDirectory, "reports");
		}
		return this.output;
	}

	/**
	 * @return
	 */
	protected Integer getPage() {
		return this.page;
	}

	/**
	 * @return
	 */
	protected Parameter[] getParameters() {
		return this.parameters;
	}

	/**
	 * @return
	 */
	protected File getParametersFile() {
		return this.parametersFile;
	}

	/**
	 * @return
	 * @throws MojoExecutionException
	 */
	protected File[] getReports() throws MojoExecutionException {
		try {
			File directory = new File(this.reports.getDirectory());
			String includes = getCommaSeparatedList(this.reports.getIncludes());
			String excludes = getCommaSeparatedList(this.reports.getExcludes());
			List files = FileUtils.getFiles(directory, includes, excludes);
			return (File[]) files.toArray(new File[files.size()]);
		} catch (IOException e) {
			throw new MojoExecutionException("Unable to get paths to reprots", e);
		}
	}

	/**
	 * @return
	 */
	protected abstract ReportRunner instantiateReportRunner();

	/**
	 * Sets 'birtHome' parameter value
	 * 
	 * @param birtHome
	 */
	public void setBirtHome(String birtHome) {
		this.birtHome = birtHome;
	}

	/**
	 * @param format
	 *            the format to set
	 * @throws MojoExecutionException
	 */
	public void setFormat(String format) throws MojoExecutionException {
		this.format = format;
	}

	/**
	 * @param locale
	 */
	public void setLocale(String locale) {
		this.locale = locale;
	}

	/**
	 * @param output
	 */
	public void setOutput(File output) {
		this.output = output;
	}

	/**
	 * Currently applicable just for render mode.
	 * 
	 * @param page
	 */
	// TODO > provide also for runrender mode - requires new RunRender
	// implementation
	public void setPage(Integer page) {
		this.page = page;
	}

	public void setParametersFile(File parametersFile) {
		this.parametersFile = parametersFile;
	}
}
